from rest_framework.generics import ListAPIView, RetrieveAPIView, CreateAPIView
from api import models
from rest_framework import serializers
import datetime
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import exceptions
from api.authentication.auth import GeneralAuthentication, UserAuthentication
from api.pagination.pages import OrderBaseFilterBackend, SocialListLimitOffsetPagination, MaxBaseFilterBackend
from script.sqlheper import SqlHelper
from django.db.models import Q


class UserInfoModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.UserInfo
        fields = "__all__"


class SocialModelSerializer(serializers.ModelSerializer):
    comment_count = serializers.SerializerMethodField()
    isFollow = serializers.SerializerMethodField()
    username = serializers.CharField(source='user.username')
    userpic = serializers.CharField(source='user.avatar')
    news_list = serializers.SerializerMethodField()

    class Meta:
        model = models.Posts
        # fields = "__all__"
        exclude = ["support_count", "unsupport_count", "topic"]

    def get_comment_count(self, obj):
        count = models.Comment.objects.filter(posts=obj).count()
        return count

    def get_isFollow(self, obj):
        user_object = self.context['request'].user
        if not user_object:
            return False

        return models.Follow.objects.filter(user_follow=obj.user, user=user_object).exists()

    def get_news_list(self, obj):
        user_object = self.context['request'].user
        news_list = {'type': "", "support_count": obj.support_count, "unsupport_count": obj.unsupport_count}
        if not user_object:
            return news_list
        news_object = models.PostsRecord.objects.filter(posts=obj, user=user_object).first()
        if not news_object:
            return news_list

        news_list['type'] = news_object.get_status_display()
        return news_list


class SocialView(ListAPIView):
    queryset = models.Posts.objects.filter(topic__isnull=True)
    serializer_class = SocialModelSerializer
    authentication_classes = [GeneralAuthentication, ]
    pagination_class = SocialListLimitOffsetPagination
    filter_backends = [MaxBaseFilterBackend]

    def get_queryset(self):
        status = self.request.GET.get('status', None)
        if status:
            return self.queryset.filter(topic__isnull=True, status=status)
        return self.queryset.filter(topic__isnull=True, status=1)

    def get(self, request, *args, **kwargs):
        response = super().get(request, *args, **kwargs)
        status = self.request.GET.get('status', None)
        if not status:
            tabBars = [{'id': status_tuple[0], 'name': status_tuple[1]} for status_tuple in models.Posts.status_choices]
            response.data = {
                'tabBars': tabBars,
                'list': response.data
            }
        return response


class SocialDetailView(RetrieveAPIView):
    queryset = models.Posts.objects
    serializer_class = SocialModelSerializer
    authentication_classes = [GeneralAuthentication, ]

    def get_queryset(self):
        pk = self.kwargs.get('pk')
        path = self.request.path_info.split('/')[2]
        if path == 'social':
            return self.queryset.filter(id=pk, topic__isnull=True)
        return self.queryset.filter(id=pk, status__isnull=True)

    def get(self, request, *args, **kwargs):
        response = super().get(request, *args, **kwargs)
        result = {}
        result['list'] = response.data
        posts_img = models.PostsImages.objects.filter(posts_id=result["list"]['id']).values()
        result['images'] = [{"url": item['images']} for item in posts_img]
        comment_list = models.Comment.objects.filter(posts=result["list"]['id'])
        result['comments'] = []
        for item in comment_list:
            result['comments'].append(
                {"id": item.id, "content": item.content, "userpic": item.user.avatar, "username": item.user.username,
                 "time": item.create_date, "reply": item.reply.id if item.reply else None})
        response.data = result
        return response


class SocialImagesModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.PostsImages
        exclude = ['posts']


class SocialAddModelSerializer(serializers.ModelSerializer):
    images = SocialImagesModelSerializer(many=True)

    class Meta:
        model = models.Posts
        # fields = "__all__"
        exclude = ['titlepic', 'user']

    def validate_images(self, value):
        if not value:
            raise exceptions.ValidationError('封面不能为空')
        return value

    def create(self, validated_data):
        images_list = validated_data.pop('images')
        validated_data['user'] = self.context['request'].user
        validated_data['titlepic'] = images_list[0]['images']
        posts_object = models.Posts.objects.create(**validated_data)

        # 保存到NewsDetail表中(通过bulk_create获取对象列表一并添加)
        data_object = models.PostsImages.objects.bulk_create(
            [models.PostsImages(images=info['images'], posts=posts_object) for info in images_list])
        posts_object.images = data_object

        return posts_object


class SocialAddView(CreateAPIView):
    queryset = models.Posts.objects
    serializer_class = SocialAddModelSerializer
    authentication_classes = [UserAuthentication]


class ConcernedView(ListAPIView):
    authentication_classes = [UserAuthentication, ]
    serializer_class = SocialModelSerializer
    pagination_class = SocialListLimitOffsetPagination
    filter_backends = [MaxBaseFilterBackend]

    def get_queryset(self):
        follow_list = models.Follow.objects.filter(user=self.request.user).all()
        user_list = [row.user_follow for row in follow_list]
        posts_list = models.Posts.objects.filter(user_id__in=user_list, topic__isnull=True).all().order_by('id')
        return posts_list


class TopicModelSerializer(serializers.ModelSerializer):
    today_count = serializers.SerializerMethodField()
    news_count = serializers.SerializerMethodField()

    class Meta:
        model = models.Topic
        fields = "__all__"

    def get_today_count(self, obj):
        posts_object = models.Posts.objects.filter(topic=obj, status__isnull=True)
        if not posts_object.count():
            return 0
        now_time = datetime.datetime.now() - datetime.timedelta(hours=24)
        topic_object = posts_object.filter(create_date__gt=now_time)
        return topic_object.count()

    def get_news_count(self, obj):
        count = models.Posts.objects.filter(topic=obj, status__isnull=True).count()

        return count


class TopicView(ListAPIView):
    queryset = models.Topic.objects
    serializer_class = TopicModelSerializer
    authentication_classes = [GeneralAuthentication, ]

    def get(self, request, *args, **kwargs):
        response = super().get(request, *args, **kwargs)
        topic_choices = models.Topic.status_choices
        tabBars = []
        data_list = {}
        result = response.data
        for status_tuple in topic_choices:
            data_list[status_tuple[0]] = {'list': []}
            tabBars.append({'id': status_tuple[0], 'name': status_tuple[1]})
        callback = request.GET.get('callback')
        """
            当callback有值时则进行分组
        """
        if not callback:
            response.data = {
                'tabBars': tabBars,
                'list': result
            }
            return response
        for row in result:
            data_list[row['status']]['list'].append(row)
        response.data = {
            'tabBars': tabBars,
            'topic_list': data_list.values()
        }
        return response


class TopicDetailView(ListAPIView):
    serializer_class = SocialModelSerializer
    filter_backends = [OrderBaseFilterBackend]
    authentication_classes = [GeneralAuthentication, ]
    pagination_class = SocialListLimitOffsetPagination

    def get_queryset(self):
        pk = self.kwargs.get('pk')
        queryset = models.Posts.objects.filter(status__isnull=True, topic_id=pk)
        return queryset


class NewsModelSerializer(serializers.ModelSerializer):
    type = serializers.CharField(source='get_type_display')
    username = serializers.SerializerMethodField()
    avatar = serializers.SerializerMethodField()

    class Meta:
        model = models.News
        fields = "__all__"

    def get_username(self, obj):
        user_object = self.context['request'].user
        # 如果不是当前用户
        if not user_object == obj.user:
            return obj.user.username
        return obj.receive_user.username

    def get_avatar(self, obj):
        user_object = self.context['request'].user
        # 如果不是当前用户
        if user_object == obj.user:
            return obj.receive_user.avatar
        return obj.user.avatar


class NewsDetailModelSerializer(serializers.ModelSerializer):
    type = serializers.CharField(source='get_type_display')
    username = serializers.CharField(source='user.avatar')
    avatar = serializers.CharField(source='user.avatar')

    class Meta:
        model = models.News
        fields = "__all__"


class NewsView(ListAPIView):
    queryset = models.News.objects
    serializer_class = NewsModelSerializer
    authentication_classes = [UserAuthentication]

    def get_queryset(self):
        user_object = self.request.user
        return self.queryset.filter(Q(user=user_object) | Q(receive_user=user_object)).order_by('-create_date')

    def get(self, request, *args, **kwargs):
        response = super().get(request, *args, **kwargs)
        result = response.data
        data_list = {}
        total = 0
        for item in result:
            if item['user'] in data_list or item['receive_user'] in data_list:
                continue
            if item['user'] == request.user.id:
                data_list[item['receive_user']] = item
                total += item['unread']
                continue
            data_list[item['user']] = item
            total += item['unread']
        response.data = data_list.values()
        return response


class NewsDetailView(ListAPIView):
    queryset = models.News.objects
    serializer_class = NewsDetailModelSerializer
    authentication_classes = [UserAuthentication]

    def get_queryset(self):
        user_object = self.request.user
        detail = self.kwargs.get('pk')
        return self.queryset.filter(Q(user=user_object) & Q(receive_user_id=detail) |
                                    Q(user_id=detail) & Q(receive_user=user_object)).order_by('create_date')


class FollowModelSerializer(serializers.ModelSerializer):
    isFollow = serializers.SerializerMethodField()
    username = serializers.SerializerMethodField()
    avatar = serializers.SerializerMethodField()
    sex = serializers.SerializerMethodField()
    age = serializers.SerializerMethodField()

    def get_username(self, obj):
        user_object = self.context['request'].user
        if not user_object:
            return obj.user.username
        if user_object == obj.user:
            return obj.user_follow.username
        return obj.user.username

    def get_avatar(self, obj):
        user_object = self.context['request'].user
        if not user_object:
            return obj.user.avatar
        if user_object == obj.user:
            return obj.user_follow.avatar
        return obj.user.avatar

    def get_isFollow(self, obj):
        user_object = self.context['request'].user
        if not user_object:
            return False
        if user_object == obj.user:
            return models.Follow.objects.filter(user=user_object, user_follow=obj.user_follow).exists()
        return models.Follow.objects.filter(user=user_object, user_follow=obj.user, status=1).exists()

    def get_sex(self, obj):
        queryset = models.UserData.objects
        user_object = self.context['request'].user
        if not user_object:
            return False
        if user_object == obj.user_follow:
            user_data = queryset.filter(user=obj.user).first()
        else:
            user_data = queryset.filter(user=obj.user_follow).first()
        if not user_data:
            return 0
        return user_data.sex

    def get_age(self, obj):
        queryset = models.UserData.objects
        user_object = self.context['request'].user
        if user_object == obj.user_follow:
            user_data = queryset.filter(user=obj.user).first()
        else:
            user_data = queryset.filter(user=obj.user_follow).first()
        if not user_data:
            return "保密"
        return user_data.birthday

    class Meta:
        model = models.Follow
        fields = "__all__"


class FollowAddModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Follow
        fields = []

    def create(self, validated_data):
        pk = self.context['view'].kwargs.get('pk')
        validated_data['user'] = self.context['request'].user
        validated_data['user_follow'] = models.UserInfo.objects.filter(id=pk).first()
        # 判断对方是否关注当前用户
        queryset = models.Follow.objects
        user_follow_object = queryset.filter(user_follow=validated_data['user'], user_id=pk).first()
        # 是否关注过对方 1.关注过则取消 2.没关注则关注
        user_object = queryset.filter(**validated_data).first()
        # 对方没关注了当前用户
        if not user_follow_object:
            # 关注
            if not user_object:
                follow_object = queryset.create(**validated_data)
                return follow_object
            # 取消关注
            user_object.delete()
            return user_object
        # 对方关注了当前用户
        if not user_object:
            # 互相关注对方
            validated_data['status'] = 1
            user_follow_object.status = 1
            user_follow = queryset.create(**validated_data)
        # 当前用户取消关注,但是对方没有取消
        else:
            user_follow = user_object.delete()
            user_follow_object.status = 2
        user_follow_object.save()
        return user_follow


class FollowView(ListAPIView):
    queryset = models.Follow.objects
    serializer_class = FollowModelSerializer
    authentication_classes = [UserAuthentication]

    def get_queryset(self):
        return self.queryset.filter(user=self.request.user)

    def get(self, request, *args, **kwargs):
        response = super().get(request, *args, **kwargs)
        result_list = []
        fans_list = []
        tabBars = {}
        for status_tuple in models.Follow.status_choices:
            tabBars[status_tuple[0]] = {"name": status_tuple[1], "num": 0}
        queryset = models.Follow.objects
        for row in response.data:
            result = queryset.filter(user_follow_id=row['user'], status=1)
            # 互关
            if result:
                tabBars[1]['num'] = result.count()
                form = FollowModelSerializer(instance=result, many=True, context={'request': request})
                result_list = form.data
                break

        fans = queryset.filter(user_follow=request.user, status=2)
        # 粉丝
        if fans:
            tabBars[3]['num'] = fans.count()
            fans_form = FollowModelSerializer(instance=fans, many=True, context={'request': request})
            fans_list = fans_form.data
        tabBars[2]['num'] = len(response.data)
        data_list = [{'list': result_list}, {'list': response.data}, {'list': fans_list}]
        response.data = [{'tabBars': tabBars.values()}, {'data_list': data_list}]
        return response


class FollowAdd(CreateAPIView):
    queryset = models.Follow.objects
    serializer_class = FollowAddModelSerializer
    authentication_classes = [UserAuthentication]


class FavorRecordModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.PostsRecord
        fields = ["status"]

    def create(self, validated_data):
        pk = self.context['view'].kwargs.get('pk')
        validated_data['posts'] = models.Posts.objects.filter(id=pk).first()
        validated_data['user'] = self.context['request'].user
        record_object = models.PostsRecord.objects.filter(**validated_data).first()
        # 如果不存在则有2种可能 1.没有进行操作 2.操作过了但类型不对
        if not record_object:
            favor_object = models.PostsRecord.objects.filter(user=validated_data['user'],
                                                             posts=validated_data['posts']).first()
            # 第1种可能
            if not favor_object:
                posts_object = models.PostsRecord.objects.create(**validated_data)
                if posts_object.status == 1:
                    validated_data['posts'].support_count += 1
                else:
                    validated_data['posts'].unsupport_count += 1
                validated_data['posts'].save()
                return posts_object
            if favor_object.status == 1:
                validated_data['posts'].support_count -= 1
                validated_data['posts'].unsupport_count += 1
            else:
                validated_data['posts'].support_count += 1
                validated_data['posts'].unsupport_count -= 1
            validated_data['posts'].save()
            favor_object.status = validated_data['status']
            favor_object.save()
            return favor_object
        # 如果存在说明是取消选择状态
        else:
            if record_object.status == 1:
                validated_data['posts'].support_count -= 1
            else:
                validated_data['posts'].unsupport_count -= 1

            validated_data['posts'].save()
            delete_object = record_object.delete()
            return delete_object


class FavorRecordView(CreateAPIView):
    queryset = models.PostsRecord.objects
    serializer_class = FavorRecordModelSerializer
    authentication_classes = [UserAuthentication]

    def perform_create(self, serializer):
        serializer.save()


class CommentModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Comment
        # fields = "__all__"
        exclude = ['posts', 'user']

    def create(self, validated_data):
        validated_data['user'] = self.context['request'].user
        pk = self.context['view'].kwargs.get('pk')
        validated_data['posts'] = models.Posts.objects.filter(id=pk).first()
        comment_object = models.Comment.objects.create(**validated_data)
        return comment_object


class CommentAddView(CreateAPIView):
    queryset = models.Comment.objects
    serializer_class = CommentModelSerializer
    authentication_classes = [UserAuthentication]

    def perform_create(self, serializer):
        serializer.save()


class CommentFavorModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.CommentFavorRecord
        fields = ["comment"]

    def create(self, validated_data):
        validated_data['user'] = self.context['request'].user
        comment_favor_object = models.CommentFavorRecord.objects.filter(**validated_data).first()
        if not comment_favor_object:
            comment_favor_object = models.CommentFavorRecord.objects.create(**validated_data)
            comment_favor_object.comment.favor_count += 1

        else:
            comment_favor_object.comment.favor_count -= 1
            comment_favor_object.delete()

        comment_favor_object.comment.save()
        return comment_favor_object


class CommentFavorView(CreateAPIView):
    queryset = models.CommentFavorRecord.objects
    serializer_class = CommentFavorModelSerializer
    authentication_classes = [UserAuthentication]

    def perform_create(self, serializer):
        serializer.save()


class NewsAddViewModelSerializer(serializers.ModelSerializer):
    username = serializers.CharField(read_only=True, source="user.username")
    avatar = serializers.CharField(read_only=True, source="user.avatar")

    class Meta:
        model = models.News
        fields = "__all__"


class NewsAddView(CreateAPIView):
    queryset = models.News.objects
    serializer_class = NewsAddViewModelSerializer
    authentication_classes = [UserAuthentication]


class UserInfoSearchModelSerializer(serializers.ModelSerializer):
    sex = serializers.SerializerMethodField()
    age = serializers.SerializerMethodField()
    isFollow = serializers.SerializerMethodField()

    def get_age(self, obj):
        user_data = models.UserData.objects.filter(user_id=obj['id']).first()
        if not user_data:
            return "保密"
        return user_data.birthday

    def get_sex(self, obj):
        user_data = models.UserData.objects.filter(user_id=obj['id']).first()
        if not user_data:
            return 0
        return user_data.sex

    def get_isFollow(self, obj):
        user_object = self.context['request'].user
        if not user_object:
            return False
        return models.Follow.objects.filter(user_follow=obj['id'], user=user_object).exists()

    class Meta:
        model = models.UserInfo
        fields = ["username", "id", "avatar", "age", "sex", "isFollow"]
        # fields = "__all__"


class SearchView(APIView):
    authentication_classes = [GeneralAuthentication]

    def get(self, request, *args, **kwargs):
        obj = SqlHelper()

        search_type = request.query_params.get('type')
        data = request.query_params.get('data')
        # 帖子查找
        if search_type == "post":
            posts_list = obj.get_list("select * from api_posts where  title like %s",
                                      [('%' + data + '%')])
            posts_id_list = [row['id'] for row in posts_list]
            posts_object = models.Posts.objects.filter(id__in=posts_id_list, topic__isnull=True).all()
            ser = SocialModelSerializer(instance=posts_object, many=True, context={'request': request})
            return Response({'status': True, 'msg': ser.data})
        # 话题查找
        elif search_type == "topic":
            topic_list = obj.get_list("select id from api_topic where title like %s", [('%' + data + '%')])
            topic_id_list = [row['id'] for row in topic_list]
            topic_object = models.Topic.objects.filter(id__in=topic_id_list).all()
            ser = TopicModelSerializer(instance=topic_object, many=True, context={'request': request})
            return Response({'status': True, 'msg': ser.data})
        # 用户查找
        elif search_type == "user":
            user_list = obj.get_list("select username, id, avatar from api_userinfo where username like %s",
                                     [('%' + data + '%')])
            ser = UserInfoSearchModelSerializer(instance=user_list, many=True, context={'request': request})
            return Response({'status': True, 'msg': ser.data})
        return Response({'status': False, 'msg': "请求失败"})
